package com.izhengyin.miaosha.service;

import com.izhengyin.miaosha.CreateOrderExecutor;
import com.izhengyin.miaosha.service.external.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import java.util.Map;
import java.util.UUID;
@Service
@Slf4j
public class MiaoShaService {
    private final QueuingService queuingService;
    private final TokenService tokenService;
    private final OrderService orderService;
    public MiaoShaService(QueuingService queuingService, TokenService tokenService ,OrderService orderService) {
        this.queuingService = queuingService;
        this.tokenService = tokenService;
        this.orderService = orderService;
    }

    /**
     * 入队，并返回排队号
     * @param itemId
     * @return
     */
    public Mono<String> enqueue(long itemId){
        final String queueNumber = getQueueNumber();
        return queuingService.enqueue(itemId,queueNumber)
                .filter(b -> b)
                .map(b -> queueNumber);
    }

    /**
     * 通过排队号，获取token
     * @param queueNumber
     * @return
     */
    public Mono<String> getToken(String queueNumber){
        return tokenService.get(queueNumber)
                .defaultIfEmpty("没有找到token");
    }

    /**
     * 创建订单
     * @param itemId
     * @param mockCreateOrderArgs 模拟订单创建参数 （透传给订单系统）
     * @return
     */
    public Mono<Boolean> createOrder(long itemId , Map<String,Object> mockCreateOrderArgs){
        String queueNumber = mockCreateOrderArgs.get("queueNumber") + "";
        String token = mockCreateOrderArgs.get("token") + "";
        return Mono.just(tokenService.verify(queueNumber,token))
                .filter(Boolean::booleanValue)
                .flatMap(b ->
                        //使用独立的线程池处理生成订单，控制速率
                        Mono.just("")
                            .subscribeOn(Schedulers.fromExecutor(CreateOrderExecutor.getExecutor()))
                            .map(none -> orderService.createOrder(itemId,mockCreateOrderArgs))
                );
    }

    /**
     * 获取队列号，采用本地生成
     * @return
     */
    private String getQueueNumber(){
        return UUID.randomUUID().toString();
    }
}
